1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 package sun.security.pkcs;
27
28 import java.io.IOException;
29 import java.io.OutputStream;
30 import java.security.cert.CertificateException;
31 import java.util.Locale;
32 import java.util.Date;
33 import java.util.Hashtable;
34 import sun.security.x509.CertificateExtensions;
35 import sun.security.util.Debug;
36 import sun.security.util.DerEncoder;
37 import sun.security.util.DerValue;
38 import sun.security.util.DerInputStream;
39 import sun.security.util.DerOutputStream;
40 import sun.security.util.ObjectIdentifier;
41 import sun.misc.HexDumpEncoder;
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178 public class PKCS9Attribute implements DerEncoder {
179
180
181 private static final Debug debug = Debug.getInstance("jar");
182
183
184
185
186 static final ObjectIdentifier[] PKCS9_OIDS = new ObjectIdentifier[18];
187
188 static {
189 for (int i = 1; i < PKCS9_OIDS.length - 2; i++) {
190 PKCS9_OIDS[i] =
191 ObjectIdentifier.newInternal(new int[]{1,2,840,113549,1,9,i});
192 }
193
194
195 PKCS9_OIDS[PKCS9_OIDS.length - 2] =
196 ObjectIdentifier.newInternal(new int[]{1,2,840,113549,1,9,16,2,12});
197 PKCS9_OIDS[PKCS9_OIDS.length - 1] =
198 ObjectIdentifier.newInternal(new int[]{1,2,840,113549,1,9,16,2,14});
199 }
200
201
202 public static final ObjectIdentifier EMAIL_ADDRESS_OID = PKCS9_OIDS[1];
203 public static final ObjectIdentifier UNSTRUCTURED_NAME_OID = PKCS9_OIDS[2];
204 public static final ObjectIdentifier CONTENT_TYPE_OID = PKCS9_OIDS[3];
205 public static final ObjectIdentifier MESSAGE_DIGEST_OID = PKCS9_OIDS[4];
206 public static final ObjectIdentifier SIGNING_TIME_OID = PKCS9_OIDS[5];
207 public static final ObjectIdentifier COUNTERSIGNATURE_OID = PKCS9_OIDS[6];
208 public static final ObjectIdentifier CHALLENGE_PASSWORD_OID = PKCS9_OIDS[7];
209 public static final ObjectIdentifier UNSTRUCTURED_ADDRESS_OID = PKCS9_OIDS[8];
210 public static final ObjectIdentifier EXTENDED_CERTIFICATE_ATTRIBUTES_OID
211 = PKCS9_OIDS[9];
212 public static final ObjectIdentifier ISSUER_SERIALNUMBER_OID = PKCS9_OIDS[10];
213
214
215 public static final ObjectIdentifier EXTENSION_REQUEST_OID = PKCS9_OIDS[14];
216 public static final ObjectIdentifier SMIME_CAPABILITY_OID = PKCS9_OIDS[15];
217 public static final ObjectIdentifier SIGNING_CERTIFICATE_OID = PKCS9_OIDS[16];
218 public static final ObjectIdentifier SIGNATURE_TIMESTAMP_TOKEN_OID =
219 PKCS9_OIDS[17];
220 public static final String EMAIL_ADDRESS_STR = "EmailAddress";
221 public static final String UNSTRUCTURED_NAME_STR = "UnstructuredName";
222 public static final String CONTENT_TYPE_STR = "ContentType";
223 public static final String MESSAGE_DIGEST_STR = "MessageDigest";
224 public static final String SIGNING_TIME_STR = "SigningTime";
225 public static final String COUNTERSIGNATURE_STR = "Countersignature";
226 public static final String CHALLENGE_PASSWORD_STR = "ChallengePassword";
227 public static final String UNSTRUCTURED_ADDRESS_STR = "UnstructuredAddress";
228 public static final String EXTENDED_CERTIFICATE_ATTRIBUTES_STR =
229 "ExtendedCertificateAttributes";
230 public static final String ISSUER_SERIALNUMBER_STR = "IssuerAndSerialNumber";
231
232 private static final String RSA_PROPRIETARY_STR = "RSAProprietary";
233
234 private static final String SMIME_SIGNING_DESC_STR = "SMIMESigningDesc";
235 public static final String EXTENSION_REQUEST_STR = "ExtensionRequest";
236 public static final String SMIME_CAPABILITY_STR = "SMIMECapability";
237 public static final String SIGNING_CERTIFICATE_STR = "SigningCertificate";
238 public static final String SIGNATURE_TIMESTAMP_TOKEN_STR =
239 "SignatureTimestampToken";
240
241
242
243
244
245
246 private static final Hashtable<String, ObjectIdentifier> NAME_OID_TABLE =
247 new Hashtable<String, ObjectIdentifier>(18);
248
249 static {
250 NAME_OID_TABLE.put("emailaddress", PKCS9_OIDS[1]);
251 NAME_OID_TABLE.put("unstructuredname", PKCS9_OIDS[2]);
252 NAME_OID_TABLE.put("contenttype", PKCS9_OIDS[3]);
253 NAME_OID_TABLE.put("messagedigest", PKCS9_OIDS[4]);
254 NAME_OID_TABLE.put("signingtime", PKCS9_OIDS[5]);
255 NAME_OID_TABLE.put("countersignature", PKCS9_OIDS[6]);
256 NAME_OID_TABLE.put("challengepassword", PKCS9_OIDS[7]);
257 NAME_OID_TABLE.put("unstructuredaddress", PKCS9_OIDS[8]);
258 NAME_OID_TABLE.put("extendedcertificateattributes", PKCS9_OIDS[9]);
259 NAME_OID_TABLE.put("issuerandserialnumber", PKCS9_OIDS[10]);
260 NAME_OID_TABLE.put("rsaproprietary", PKCS9_OIDS[11]);
261 NAME_OID_TABLE.put("rsaproprietary", PKCS9_OIDS[12]);
262 NAME_OID_TABLE.put("signingdescription", PKCS9_OIDS[13]);
263 NAME_OID_TABLE.put("extensionrequest", PKCS9_OIDS[14]);
264 NAME_OID_TABLE.put("smimecapability", PKCS9_OIDS[15]);
265 NAME_OID_TABLE.put("signingcertificate", PKCS9_OIDS[16]);
266 NAME_OID_TABLE.put("signaturetimestamptoken", PKCS9_OIDS[17]);
267 };
268
269
270
271
272
273 private static final Hashtable<ObjectIdentifier, String> OID_NAME_TABLE =
274 new Hashtable<ObjectIdentifier, String>(16);
275 static {
276 OID_NAME_TABLE.put(PKCS9_OIDS[1], EMAIL_ADDRESS_STR);
277 OID_NAME_TABLE.put(PKCS9_OIDS[2], UNSTRUCTURED_NAME_STR);
278 OID_NAME_TABLE.put(PKCS9_OIDS[3], CONTENT_TYPE_STR);
279 OID_NAME_TABLE.put(PKCS9_OIDS[4], MESSAGE_DIGEST_STR);
280 OID_NAME_TABLE.put(PKCS9_OIDS[5], SIGNING_TIME_STR);
281 OID_NAME_TABLE.put(PKCS9_OIDS[6], COUNTERSIGNATURE_STR);
282 OID_NAME_TABLE.put(PKCS9_OIDS[7], CHALLENGE_PASSWORD_STR);
283 OID_NAME_TABLE.put(PKCS9_OIDS[8], UNSTRUCTURED_ADDRESS_STR);
284 OID_NAME_TABLE.put(PKCS9_OIDS[9], EXTENDED_CERTIFICATE_ATTRIBUTES_STR);
285 OID_NAME_TABLE.put(PKCS9_OIDS[10], ISSUER_SERIALNUMBER_STR);
286 OID_NAME_TABLE.put(PKCS9_OIDS[11], RSA_PROPRIETARY_STR);
287 OID_NAME_TABLE.put(PKCS9_OIDS[12], RSA_PROPRIETARY_STR);
288 OID_NAME_TABLE.put(PKCS9_OIDS[13], SMIME_SIGNING_DESC_STR);
289 OID_NAME_TABLE.put(PKCS9_OIDS[14], EXTENSION_REQUEST_STR);
290 OID_NAME_TABLE.put(PKCS9_OIDS[15], SMIME_CAPABILITY_STR);
291 OID_NAME_TABLE.put(PKCS9_OIDS[16], SIGNING_CERTIFICATE_STR);
292 OID_NAME_TABLE.put(PKCS9_OIDS[17], SIGNATURE_TIMESTAMP_TOKEN_STR);
293 }
294
295
296
297
298
299
300 private static final Byte[][] PKCS9_VALUE_TAGS = {
301 null,
302 {new Byte(DerValue.tag_IA5String)},
303 {new Byte(DerValue.tag_IA5String)},
304 {new Byte(DerValue.tag_ObjectId)},
305 {new Byte(DerValue.tag_OctetString)},
306 {new Byte(DerValue.tag_UtcTime)},
307 {new Byte(DerValue.tag_Sequence)},
308 {new Byte(DerValue.tag_PrintableString),
309 new Byte(DerValue.tag_T61String)},
310 {new Byte(DerValue.tag_PrintableString),
311 new Byte(DerValue.tag_T61String)},
312 {new Byte(DerValue.tag_SetOf)},
313 {new Byte(DerValue.tag_Sequence)},
314 null,
315 null,
316 null,
317 {new Byte(DerValue.tag_Sequence)},
318 {new Byte(DerValue.tag_Sequence)},
319 {new Byte(DerValue.tag_Sequence)},
320 {new Byte(DerValue.tag_Sequence)}
321 };
322
323 private static final Class[] VALUE_CLASSES = new Class[18];
324
325 static {
326 try {
327 Class str = Class.forName("[Ljava.lang.String;");
328
329 VALUE_CLASSES[0] = null;
330 VALUE_CLASSES[1] = str;
331 VALUE_CLASSES[2] = str;
332 VALUE_CLASSES[3] =
333 Class.forName("sun.security.util.ObjectIdentifier");
334 VALUE_CLASSES[4] = Class.forName("[B");
335 VALUE_CLASSES[5] = Class.forName("java.util.Date");
336 VALUE_CLASSES[6] =
337 Class.forName("[Lsun.security.pkcs.SignerInfo;");
338 VALUE_CLASSES[7] =
339 Class.forName("java.lang.String");
340 VALUE_CLASSES[8] = str;
341 VALUE_CLASSES[9] = null;
342 VALUE_CLASSES[10] = null;
343 VALUE_CLASSES[11] = null;
344 VALUE_CLASSES[12] = null;
345 VALUE_CLASSES[13] = null;
346 VALUE_CLASSES[14] =
347 Class.forName("sun.security.x509.CertificateExtensions");
348 VALUE_CLASSES[15] = null;
349 VALUE_CLASSES[16] = null;
350 VALUE_CLASSES[17] = Class.forName("[B");
351 } catch (ClassNotFoundException e) {
352 throw new ExceptionInInitializerError(e.toString());
353 }
354 }
355
356
357
358
359
360 private static final boolean[] SINGLE_VALUED = {
361 false,
362 false,
363 false,
364 true,
365 true,
366 true,
367 false,
368 true,
369 false,
370 false,
371 true,
372 false,
373 false,
374 false,
375 true,
376 true,
377 true,
378 true
379 };
380
381
382
383
384 private int index;
385
386
387
388
389
390 private Object value;
391
392
393
394
395
396
397
398
399
400
401
402
403
404 public PKCS9Attribute(ObjectIdentifier oid, Object value)
405 throws IllegalArgumentException {
406 init(oid, value);
407 }
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425 public PKCS9Attribute(String name, Object value)
426 throws IllegalArgumentException {
427 ObjectIdentifier oid = getOID(name);
428
429 if (oid == null)
430 throw new IllegalArgumentException(
431 "Unrecognized attribute name " + name +
432 " constructing PKCS9Attribute.");
433
434 init(oid, value);
435 }
436
437 private void init(ObjectIdentifier oid, Object value)
438 throws IllegalArgumentException {
439
440 index = indexOf(oid, PKCS9_OIDS, 1);
441
442 if (index == -1)
443 throw new IllegalArgumentException(
444 "Unsupported OID " + oid +
445 " constructing PKCS9Attribute.");
446
447 if (!VALUE_CLASSES[index].isInstance(value))
448 throw new IllegalArgumentException(
449 "Wrong value class " +
450 " for attribute " + oid +
451 " constructing PKCS9Attribute; was " +
452 value.getClass().toString() + ", should be " +
453 VALUE_CLASSES[index].toString());
454
455 this.value = value;
456 }
457
458
459
460
461
462
463
464
465
466 public PKCS9Attribute(DerValue derVal) throws IOException {
467
468 DerInputStream derIn = new DerInputStream(derVal.toByteArray());
469 DerValue[] val = derIn.getSequence(2);
470
471 if (derIn.available() != 0)
472 throw new IOException("Excess data parsing PKCS9Attribute");
473
474 if (val.length != 2)
475 throw new IOException("PKCS9Attribute doesn't have two components");
476
477
478 ObjectIdentifier oid = val[0].getOID();
479 index = indexOf(oid, PKCS9_OIDS, 1);
480 if (index == -1) {
481 if (debug != null) {
482 debug.println("ignoring unsupported signer attribute: " + oid);
483 }
484 throw new ParsingException("Unsupported PKCS9 attribute: " + oid);
485 }
486
487 DerValue[] elems = new DerInputStream(val[1].toByteArray()).getSet(1);
488
489 if (SINGLE_VALUED[index] && elems.length > 1)
490 throwSingleValuedException();
491
492
493 Byte tag;
494 for (int i=0; i < elems.length; i++) {
495 tag = new Byte(elems[i].tag);
496
497 if (indexOf(tag, PKCS9_VALUE_TAGS[index], 0) == -1)
498 throwTagException(tag);
499 }
500
501 switch (index) {
502 case 1:
503 case 2:
504 case 8:
505 {
506 String[] values = new String[elems.length];
507
508 for (int i=0; i < elems.length; i++)
509 values[i] = elems[i].getAsString();
510 value = values;
511 }
512 break;
513
514 case 3:
515 value = elems[0].getOID();
516 break;
517
518 case 4:
519 value = elems[0].getOctetString();
520 break;
521
522 case 5:
523 value = (new DerInputStream(elems[0].toByteArray())).getUTCTime();
524 break;
525
526 case 6:
527 {
528 SignerInfo[] values = new SignerInfo[elems.length];
529 for (int i=0; i < elems.length; i++)
530 values[i] =
531 new SignerInfo(elems[i].toDerInputStream());
532 value = values;
533 }
534 break;
535
536 case 7:
537 value = elems[0].getAsString();
538 break;
539
540 case 9:
541 throw new IOException("PKCS9 extended-certificate " +
542 "attribute not supported.");
543
544 case 10:
545 throw new IOException("PKCS9 IssuerAndSerialNumber" +
546 "attribute not supported.");
547
548 case 11:
549 case 12:
550 throw new IOException("PKCS9 RSA DSI attributes" +
551 "11 and 12, not supported.");
552
553 case 13:
554 throw new IOException("PKCS9 attribute #13 not supported.");
555
556
557 case 14:
558 value = new CertificateExtensions(
559 new DerInputStream(elems[0].toByteArray()));
560 break;
561
562 case 15:
563 throw new IOException("PKCS9 SMIMECapability " +
564 "attribute not supported.");
565
566 case 16:
567 value = new SigningCertificateInfo(elems[0].toByteArray());
568 break;
569
570 case 17:
571 value = elems[0].toByteArray();
572 break;
573 default:
574 }
575 }
576
577
578
579
580
581
582
583
584
585 public void derEncode(OutputStream out) throws IOException {
586 DerOutputStream temp = new DerOutputStream();
587 temp.putOID(getOID());
588 switch (index) {
589 case 1:
590 case 2:
591 {
592 String[] values = (String[]) value;
593 DerOutputStream[] temps = new
594 DerOutputStream[values.length];
595
596 for (int i=0; i < values.length; i++) {
597 temps[i] = new DerOutputStream();
598 temps[i].putIA5String( values[i]);
599 }
600 temp.putOrderedSetOf(DerValue.tag_Set, temps);
601 }
602 break;
603
604 case 3:
605 {
606 DerOutputStream temp2 = new DerOutputStream();
607 temp2.putOID((ObjectIdentifier) value);
608 temp.write(DerValue.tag_Set, temp2.toByteArray());
609 }
610 break;
611
612 case 4:
613 {
614 DerOutputStream temp2 = new DerOutputStream();
615 temp2.putOctetString((byte[]) value);
616 temp.write(DerValue.tag_Set, temp2.toByteArray());
617 }
618 break;
619
620 case 5:
621 {
622 DerOutputStream temp2 = new DerOutputStream();
623 temp2.putUTCTime((Date) value);
624 temp.write(DerValue.tag_Set, temp2.toByteArray());
625 }
626 break;
627
628 case 6:
629 temp.putOrderedSetOf(DerValue.tag_Set, (DerEncoder[]) value);
630 break;
631
632 case 7:
633 {
634 DerOutputStream temp2 = new DerOutputStream();
635 temp2.putPrintableString((String) value);
636 temp.write(DerValue.tag_Set, temp2.toByteArray());
637 }
638 break;
639
640 case 8:
641 {
642 String[] values = (String[]) value;
643 DerOutputStream[] temps = new
644 DerOutputStream[values.length];
645
646 for (int i=0; i < values.length; i++) {
647 temps[i] = new DerOutputStream();
648 temps[i].putPrintableString(values[i]);
649 }
650 temp.putOrderedSetOf(DerValue.tag_Set, temps);
651 }
652 break;
653
654 case 9:
655 throw new IOException("PKCS9 extended-certificate " +
656 "attribute not supported.");
657
658 case 10:
659 throw new IOException("PKCS9 IssuerAndSerialNumber" +
660 "attribute not supported.");
661
662 case 11:
663 case 12:
664 throw new IOException("PKCS9 RSA DSI attributes" +
665 "11 and 12, not supported.");
666
667 case 13:
668 throw new IOException("PKCS9 attribute #13 not supported.");
669
670
671 case 14:
672 {
673 DerOutputStream temp2 = new DerOutputStream();
674 CertificateExtensions exts = (CertificateExtensions)value;
675 try {
676 exts.encode(temp2, true);
677 } catch (CertificateException ex) {
678 throw new IOException(ex.toString());
679 }
680 temp.write(DerValue.tag_Set, temp2.toByteArray());
681 }
682 break;
683 case 15:
684 throw new IOException("PKCS9 attribute #15 not supported.");
685
686
687 case 16:
688 throw new IOException(
689 "PKCS9 SigningCertificate attribute not supported.");
690
691
692 case 17:
693 temp.write(DerValue.tag_Set, (byte[])value);
694 break;
695
696 default:
697 }
698
699 DerOutputStream derOut = new DerOutputStream();
700 derOut.write(DerValue.tag_Sequence, temp.toByteArray());
701
702 out.write(derOut.toByteArray());
703
704 }
705
706
707
708
709
710
711
712
713
714
715
716 public Object getValue() {
717 return value;
718 }
719
720
721
722
723 public boolean isSingleValued() {
724 return SINGLE_VALUED[index];
725 }
726
727
728
729
730 public ObjectIdentifier getOID() {
731 return PKCS9_OIDS[index];
732 }
733
734
735
736
737 public String getName() {
738 return OID_NAME_TABLE.get(PKCS9_OIDS[index]);
739 }
740
741
742
743
744
745 public static ObjectIdentifier getOID(String name) {
746 return NAME_OID_TABLE.get(name.toLowerCase(Locale.ENGLISH));
747 }
748
749
750
751
752
753 public static String getName(ObjectIdentifier oid) {
754 return OID_NAME_TABLE.get(oid);
755 }
756
757
758
759
760 public String toString() {
761 StringBuffer buf = new StringBuffer(100);
762
763 buf.append("[");
764
765 buf.append(OID_NAME_TABLE.get(PKCS9_OIDS[index]));
766 buf.append(": ");
767
768 if (SINGLE_VALUED[index]) {
769 if (value instanceof byte[]) {
770 HexDumpEncoder hexDump = new HexDumpEncoder();
771 buf.append(hexDump.encodeBuffer((byte[]) value));
772 } else {
773 buf.append(value.toString());
774 }
775 buf.append("]");
776 return buf.toString();
777 } else {
778 boolean first = true;
779 Object[] values = (Object[]) value;
780
781 for (int j=0; j < values.length; j++) {
782 if (first)
783 first = false;
784 else
785 buf.append(", ");
786
787 buf.append(values[j].toString());
788 }
789 return buf.toString();
790 }
791 }
792
793
794
795
796
797
798
799 static int indexOf(Object obj, Object[] a, int start) {
800 for (int i=start; i < a.length; i++) {
801 if (obj.equals(a[i])) return i;
802 }
803 return -1;
804 }
805
806
807
808
809
810 private void throwSingleValuedException() throws IOException {
811 throw new IOException("Single-value attribute " +
812 getOID() + " (" + getName() + ")" +
813 " has multiple values.");
814 }
815
816
817
818
819
820 private void throwTagException(Byte tag)
821 throws IOException {
822 Byte[] expectedTags = PKCS9_VALUE_TAGS[index];
823 StringBuffer msg = new StringBuffer(100);
824 msg.append("Value of attribute ");
825 msg.append(getOID().toString());
826 msg.append(" (");
827 msg.append(getName());
828 msg.append(") has wrong tag: ");
829 msg.append(tag.toString());
830 msg.append(". Expected tags: ");
831
832 msg.append(expectedTags[0].toString());
833
834 for (int i = 1; i < expectedTags.length; i++) {
835 msg.append(", ");
836 msg.append(expectedTags[i].toString());
837 }
838 msg.append(".");
839 throw new IOException(msg.toString());
840 }
841 }